package vip.liux.contracts.models.point;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import vip.liux.contracts.shared.enums.Status;
import vip.liux.contracts.shared.enums.point.PointRuleType;
import vip.liux.domain.entities.auditing.AuditedEntity;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;

/**
 * 积分规则实体类
 * 表示积分规则的定义，包括规则名称、编码、类型、积分值等信息。
 */
@Getter
@Setter
@Entity
@Table(name = "shop_points_rule", uniqueConstraints = {
        @UniqueConstraint(columnNames = "rule_code", name = "uk_rule_code")
})
public class PointsRule extends AuditedEntity<Long> {

    /**
     * 规则名称
     * 表示积分规则的名称。
     */
    @Column(name = "rule_name", nullable = false, length = 128)
    private String ruleName;

    /**
     * 规则编码
     * 表示积分规则的唯一编码。
     */
    @Column(name = "rule_code", nullable = false, length = 64)
    private String ruleCode;

    /**
     * 规则类型
     * 表示积分规则的类型，例如获取积分、消费积分等。
     */
    @Column(name = "rule_type", nullable = false)
    @Enumerated(EnumType.ORDINAL)
    private PointRuleType ruleType;

    /**
     * 有效期, 数据库中存储为秒数(NULL表示永不过期)
     */
    @Column(name = "valid_duration")
    private Duration validDuration;

    /**
     * 每日上限
     * 表示该规则每日可获取的积分上限。
     */
    @Column(name = "daily_limit")
    private BigDecimal dailyLimit;

    /**
     * 状态
     * 表示积分规则的状态，例如启用或禁用。
     */
    @Column(nullable = false)
    @Enumerated(EnumType.ORDINAL)
    private Status status;

    /**
     * 判断是否启用了过期功能
     * 如果过期天数不为空且大于0，则表示启用了过期功能。
     *
     * @return 如果启用了过期功能则返回true，否则返回false。
     */
    public boolean isExpiryEnabled() {
        return validDuration != null;
    }

    public void setId(Long id) {
        super.setId(id);
    }

    /**
     * 计算积分过期时间
     * 根据积分获取时间和过期天数计算积分的过期时间。
     *
     * @param earnTime 积分获取时间
     * @return 计算后的过期时间
     */
    public LocalDateTime calculateExpiryTime(LocalDateTime earnTime) {
        if (isExpiryEnabled()) {
            return earnTime.plus(validDuration);
        }
        return LocalDateTime.MAX; // 如果没有设置过期时间，则返回最大时间
    }
}